<template>
  <div class="image-upload" :class="{ 'is-disabled': disabled }">
    <div class="image-grid">
      <!-- 已上传的图片 -->
      <div 
        v-for="(file, index) in fileList" 
        :key="file.uid"
        class="image-preview" 
        :style="gridItemStyle"
      >
        <img 
          :src="file.url" 
          :alt="file.name" 
          class="uploaded-image" 
          @click="handlePreview(file)"
        />
        <div class="image-actions">
          <el-icon class="action-icon preview" @click.stop="handlePreview(file)">
            <ZoomIn />
          </el-icon>
          <el-icon class="action-icon delete" @click.stop="handleRemove(file, index)">
            <Delete />
          </el-icon>
        </div>
      </div>

      <!-- 上传按钮 -->
      <el-upload
        v-if="showUploadArea"
        ref="uploadRef"
        class="avatar-uploader"
        :action="uploadAction"
        :headers="uploadHeaders"
        :show-file-list="false"
        :data="formData"
        :disabled="disabled"
        :on-remove="handleRemove"
        :on-success="handleSuccess"
        :on-error="handleError"
        :before-upload="beforeUpload"
        :limit="maxFiles"
        :file-list="fileList"
        :accept="accept"
        :drag="enableDrag"
        :auto-upload="autoUpload"
      >
        <div class="upload-area" :class="{ 'is-loading': loading }">
          <el-icon v-if="loading"><Loading /></el-icon>
          <template v-else>
            <div class="upload-icon">
              <el-icon><Upload /></el-icon>
            </div>
            <div class="upload-text">
              <span>{{ uploadText }}</span>
              <span class="upload-hint">{{ uploadHint }}</span>
            </div>
          </template>
        </div>
      </el-upload>
    </div>

    <el-dialog v-model="previewVisible" :title="previewTitle" width="800px" align-center>
      <div class="preview-container">
        <img :src="previewUrl" :alt="previewTitle" class="preview-image" />
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { Delete, Loading, Upload, ZoomIn } from '@element-plus/icons-vue'


// Props 定义
const props = defineProps({
  modelValue: {
    type: Array,
    default: () => []
  },
  formData: {
    type: Object, // 上传时附带的额外参数
    default: () => ({})
  },
  maxSize: {
    type: Number, // 单个文件最大尺寸（单位：字节）
    default: 2 * 1024 * 1024 // 默认 2MB
  },
  accept: {
    type: String, // 接受的文件类型
    default: 'image/*'
  },
  maxFiles: {
    type: Number, // 最大允许上传文件数量
    default: 1
  },
  disabled: {
    type: Boolean, // 是否禁用上传功能
    default: false
  },
  enableDrag: {
    type: Boolean, // 是否启用拖拽上传
    default: true
  },
  autoUpload: {
    type: Boolean, // 是否在选择文件后自动上传
    default: true
  },
  previewSize: {
    type: Number, // 预览图片的尺寸（单位：像素）
    default: 100
  },
  uploadText: {
    type: String, // 上传区域显示的主要文本
    default: '点击或拖拽上传'
  },
  uploadHint: {
    type: String, // 上传区域显示的提示文本
    default: '支持 jpg、png 格式'
  },
  bizType: {
    type: String, // 业务类型标识
    default: ''
  }
})

// 定义组件事件
const emit = defineEmits([
  'update:modelValue', // v-model 更新事件
  'upload-success',    // 上传成功事件
  'upload-error',      // 上传失败事件
  'file-remove',       // 文件移除事件
  'file-preview'       // 文件预览事件
])

// 响应式状态变量
const fileList = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value)
})
const loading = ref(false)           // 上传加载状态
const uploadRef = ref(null)          // 上传组件引用
const previewVisible = ref(false)    // 预览对话框显示状态
const previewUrl = ref('')           // 当前预览的图片URL
const previewTitle = ref('')         // 预览对话框标题
const baseURL = ref('')              // API基础URL
const uploadAction = ref('')         // 上传接口URL
const uploadHeaders = ref({})        // 上传请求头

// 计算属性
const gridItemStyle = computed(() => ({
  width: `${props.previewSize}px`,   // 预览图片容器宽度
  height: `${props.previewSize}px`,  // 预览图片容器高度
}))

const showUploadArea = computed(() => {
  return fileList.value.length < props.maxFiles  // 是否显示上传区域
})

// 生成上传URL的方法
const generateUploadUrl = () => {
  const currentTimestamp = Date.now()                    // 当前时间戳
  const randomNum = Math.floor(Math.random() * 999) + 1  // 随机数（1-999）
  const bizId = `${currentTimestamp}${randomNum}`        // 业务ID（时间戳+随机数）
  return `${baseURL.value}system/oss/oss-simple?bizType=${props.bizType}&bizId=${bizId}`
}

// 文件上传成功处理
const handleSuccess = (response, file) => {
  loading.value = false
  const fileInfo = {
    ...file,
    url: URL.createObjectURL(file.raw),  // 本地预览URL
    data: response.data.replace(         // 实际存储URL
      'https://afl-private-dev.oss-us-east-1.aliyuncs.com',
      'http://screen.bjdnlsj.com'
    )
  }
  // 更新文件列表，只发送URL数组给父组件
  const newFileList = [...fileList.value, fileInfo]
  emit('update:modelValue', newFileList.map(file => file.data))
  emit('upload-success', response, fileInfo)
}

const handleError = (error, file) => {
  loading.value = false
  ElMessage.error('上传失败，请重试')
  emit('upload-error', error, file)
}

const handleRemove = (file, index) => {
  fileList.value = fileList.value.filter((_, i) => i !== index)
  emit('file-remove', file)
}

const handlePreview = (file) => {
  previewUrl.value = file.url
  previewTitle.value = file.name || '图片预览'
  previewVisible.value = true
  emit('file-preview', file)
}

const beforeUpload = (file) => {
  try {
    // 文件类型检查
    const isImage = file.type.startsWith('image/')
    if (!isImage) {
      ElMessage.error('只能上传图片文件！')
      return false
    }

    // 文件大小检查
    const isSizeValid = file.size <= props.maxSize
    if (!isSizeValid) {
      ElMessage.error(`文件大小不能超过 ${props.maxSize / 1024 / 1024}MB！`)
      return false
    }

    // 更新上传地址
    uploadAction.value = generateUploadUrl()
    loading.value = true
    return true
  } catch (error) {
    console.error('文件上传前检查失败:', error)
    ElMessage.error('文件检查失败，请重试')
    return false
  }
}

// 生命周期钩子
onMounted(() => {
  try {
    uploadHeaders.value = { token: localStorage.getItem('token') || '' }
    baseURL.value = process.env.NODE_ENV === 'production'
      ? 'http://10.1.5.10:9770/'
      : 'http://172.16.100.10:9770/'
    uploadAction.value = generateUploadUrl()
  } catch (error) {
    console.error('组件初始化失败:', error)
    ElMessage.error('组件初始化失败，请刷新页面重试')
  }
})
</script>

<style scoped>
.image-upload {
  width: 100%;
}

.image-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: flex-start;
}

.image-preview {
  position: relative;
  overflow: hidden;
  border: 2px solid var(--el-border-color);
  border-radius: 8px;
  transition: all 0.3s;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  background-color: var(--el-color-white);
}

.avatar-uploader {
  display: block;
  width: 100%;
}

.avatar-uploader :deep(.el-upload) {
  display: block;
  width: 100%;
  height: 100%;
}

.upload-area {
  border: 2px dashed var(--el-border-color);
  border-radius: 8px;
  text-align: center;
  cursor: pointer;
  position: relative;
  transition: all 0.3s;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: var(--el-fill-color-blank);
  height: 100%;
  width: 100%;
  padding: 8px;
}

.upload-area:hover {
  border-color: var(--el-color-primary);
  background: var(--el-color-primary-light-9);
}

.upload-area.is-loading {
  cursor: wait;
  opacity: 0.7;
}

.uploaded-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.image-actions {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  gap: 12px;
  justify-content: center;
  align-items: center;
  opacity: 0;
  transition: opacity 0.3s;
}

.image-preview:hover .image-actions {
  opacity: 1;
}

.upload-icon {
  font-size: 20px;
  color: var(--el-color-primary);
  margin-bottom: 2px;
}

.upload-text {
  color: var(--el-text-color-regular);
  font-size: 13px;
  line-height: 1.2;
}

.upload-hint {
  display: block;
  margin-top: 1px;
  color: var(--el-text-color-secondary);
  font-size: 12px;
  line-height: 1;
}

.action-icon {
  color: #fff;
  font-size: 26px;
  cursor: pointer;
  padding: 2px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.2);
  transition: all 0.3s;
  display: flex;
  align-items: center;
  justify-content: center;
}

.action-icon:hover {
  background: rgba(255, 255, 255, 0.3);
  transform: scale(1.1);
}

.action-icon.preview {
  background: var(--el-color-primary);
  color: #fff;
}

.action-icon.delete {
  background: var(--el-color-danger);
  color: #fff;
}

.preview-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 200px;
}

.preview-image {
  max-width: 100%;
  max-height: 70vh;
  object-fit: contain;
}

.is-disabled {
  cursor: not-allowed;
  opacity: 0.7;
}
</style>
